import path from 'path';
import * as fs from 'fs';

const DB_PATH = path.join(process.cwd(), 'data', 'json-database.json');

// Define the structure of our JSON database
interface Device {
  id: string;
  name: string;
  specialty: string;
  序号: string;
  classificationCode: string;
  classificationName: string;
  namingTableId: string;
  positionTableId: string;
  baseParamsTableId: string;
  techSpecTableId: string;
  备注: string;
}

interface DatabaseData {
  devices: Device[];
  measurementUnits: any[];
  parameterTableTemplates: any[];
}

interface Database extends DatabaseData {
  addDevice: (device: Device) => Device;
  addMeasurementUnit: (unit: any) => void;
  addParameterTableTemplate: (template: any) => void;
  getAllDevices: () => Device[];
  getDevicesBySpecialty: (specialty: string) => Device[];
  getDashboardStats: () => { name: string; count: number; devices: Device[] }[];
}

// The single, in-memory instance of our database
let db: Database | null = null;

/**
 * Ensures the database file exists and initializes the in-memory `db` object.
 * If the file doesn't exist, it creates a new empty database structure.
 * If it exists, it reads the content into the `db` object.
 */
function initializeDatabase() {
  if (db) return;

  try {
  if (!fs.existsSync(DB_PATH)) {
      // Create new database with empty arrays
    db = {
      devices: [],
      measurementUnits: [],
      parameterTableTemplates: [],
        addDevice: (device: Device) => {
          db!.devices.push(device);
          saveDatabase();
          return device;
        },
        addMeasurementUnit: (unit: any) => {
          db!.measurementUnits.push(unit);
          saveDatabase();
        },
        addParameterTableTemplate: (template: any) => {
          db!.parameterTableTemplates.push(template);
          saveDatabase();
        },
        getAllDevices: () => db!.devices,
        getDevicesBySpecialty: (specialty: string) => db!.devices.filter(d => d.specialty === specialty),
        getDashboardStats: () => {
          const specialties = [...new Set(db!.devices.map(d => d.specialty))];
          return specialties.map(s => ({
            name: s,
            count: db!.devices.filter(d => d.specialty === s).length,
            devices: db!.devices.filter(d => d.specialty === s),
          }));
        }
    };
    saveDatabase(); // Create the file with a valid empty structure
    return;
  }
  
  const fileContent = fs.readFileSync(DB_PATH, 'utf-8');
    let loadedDb: Partial<DatabaseData> = {};

  try {
      loadedDb = JSON.parse(fileContent);
    } catch (error) {
      console.error('Failed to parse database file:', error);
      loadedDb = {
        devices: [],
        measurementUnits: [],
        parameterTableTemplates: []
      };
    }

  db = {
    devices: loadedDb.devices || [],
    measurementUnits: loadedDb.measurementUnits || [],
    parameterTableTemplates: loadedDb.parameterTableTemplates || [],
      addDevice: (device: Device) => {
        db!.devices.push(device);
        saveDatabase();
        return device;
      },
      addMeasurementUnit: (unit: any) => {
        db!.measurementUnits.push(unit);
        saveDatabase();
      },
      addParameterTableTemplate: (template: any) => {
        db!.parameterTableTemplates.push(template);
        saveDatabase();
      },
      getAllDevices: () => db!.devices,
      getDevicesBySpecialty: (specialty: string) => db!.devices.filter(d => d.specialty === specialty),
      getDashboardStats: () => {
        const specialties = [...new Set(db!.devices.map(d => d.specialty))];
        return specialties.map(s => ({
          name: s,
          count: db!.devices.filter(d => d.specialty === s).length,
          devices: db!.devices.filter(d => d.specialty === s),
        }));
      }
    };
  } catch (error) {
    console.error('Failed to initialize database:', error);
    throw error;
  }
}

/**
 * Saves the current state of the in-memory `db` object to the JSON file.
 */
function saveDatabase() {
  fs.writeFileSync(DB_PATH, JSON.stringify(db, null, 2));
}

/**
 * Wipes all data from the database, both in-memory and on-disk.
 */
function clearDatabase() {
    db = {
      devices: [],
      measurementUnits: [],
      parameterTableTemplates: [],
    };
    saveDatabase();
}

/**
 * [PUBLIC] Returns the main database object containing all data access methods.
 */
function getDb(): Database {
  if (!db) {
    initializeDatabase();
  }

  if (!db) {
    throw new Error('Failed to initialize database');
  }

  return db;
}

// On initial module load, ensure the database is ready.
initializeDatabase();

// Export the public-facing functions
export { getDb, clearDatabase };
